export default class TimeEvent {
  constructor() {
    const url = new URL("./timeEventWorker.js", import.meta.url);
    this.worker = new Worker(url);
    this.worker.onmessage = (e) => {
      // console.log(e.data);
      this.emitEvent(e.data);
    };
    this.worker.onerror = function (e) {
      console.error(
        "worker error at " + e.filename + ":" + e.lineno + e.message
      );
    };
    this.handlers = {};
  }

  /**
   * 添加时间定时事件
   * @param {*} targetDateTime
   * @param {*} callback
   * @returns
   */
  addEvent(targetDateTime, callback) {
    if (typeof callback !== "function") {
      return console.error("参数 callback 必须是一个回调函数！");
    }
    if (!isNaN(targetDateTime) || isNaN(Date.parse(targetDateTime))) {
      return console.error("参数 targetDateTime 必须是日期格式字符串！");
    }
    const eventCallbackStack = this._getHandler(targetDateTime).callbackStack;
    eventCallbackStack.push(callback);
    this.worker.postMessage(Object.keys(this.handlers));
  }

  /**
   * 获取事件队列
   * @param {*} eventName
   * @param {*} isOnce
   * @returns
   */
  _getHandler(eventName, isOnce = false) {
    if (!this.handlers[eventName]) {
      this.handlers[eventName] = {
        isOnce,
        callbackStack: [],
      };
    }
    return this.handlers[eventName];
  }

  /**
   * 触发事件
   * @param {*} eventName
   * @param  {...any} args
   */
  emitEvent(eventName, ...args) {
    if (this.handlers[eventName]) {
      this.handlers[eventName].callbackStack.forEach((cb) => {
        // 修正this指向
        cb.call(cb, ...args);
      });
      // 移除once事件
      if (this.handlers[eventName].isOnce) {
        this.removeEvent(eventName);
      }
    }
  }

  /**
   * 移除事件
   * @param {*} eventName
   */
  removeEvent(eventName) {
    this.handlers[eventName] && delete this.handlers[eventName];
    this.worker.postMessage(Object.keys(this.handlers));
  }

  /**
   * 绑定一次性事件
   * @param {*} targetDateTime
   * @param {*} callback
   * @returns
   */
  addOnceEvent(targetDateTime, callback) {
    if (typeof callback !== "function") {
      return console.error("参数 callback 必须是一个回调函数！");
    }
    if (!isNaN(targetDateTime) || isNaN(Date.parse(targetDateTime))) {
      return console.error("参数 targetDateTime 必须是日期格式字符串！");
    }
    const eventCallbackStack = this._getHandler(
      targetDateTime,
      true
    ).callbackStack;
    eventCallbackStack.push(callback);
    this.worker.postMessage(Object.keys(this.handlers));
  }

  /**
   * 销毁worker线程，释放内存
   */
  destroy() {
    this.worker.terminate();
  }
}
